/*****************************************************
 *   > File Name: uart.c
 *   > Author: fly
 *   > Create Time: 2021-07-19  1/29  16:16:44 +0800
 *==================================================*/
#include <uart.h>
#include <libc/stdio.h>

typedef struct{
    unsigned int GPA0CON;
    unsigned int GPA0DAT;
    unsigned int GPA0PUD;
    unsigned int GPA0DRV;
    unsigned int GPA0CONPDN;
    unsigned int GPA0PUDPDN;
}gpa0;
#define GPA0    (*(volatile gpa0*)0xE0200000)

typedef struct{
    unsigned int GPA1CON;
    unsigned int GPA1DAT;
    unsigned int GPA1PUD;
    unsigned int GPA1DRV;
    unsigned int GPA1CONPDN;
    unsigned int GPA1PUDPDN;
}gpa1;
#define GPA1    (*(volatile gpa1*)0xE0200020)

typedef struct{
    unsigned int ULCON0;
    unsigned int UCON0;
    unsigned int UFCON0;
    unsigned int UMCON0;
    unsigned int UTRSTAT0;
    unsigned int UERSTAT0;
    unsigned int UFSTAT0;
    unsigned int UMSTAT0;
    unsigned int UTXH0;
    unsigned int URXH0;
    unsigned int UBRDIV0;
    unsigned int UDIVSLOT0;
    unsigned int UINTP0;
    unsigned int UINTSP0;
    unsigned int UINTM0;
}uart0;
#define UART0   (*(volatile uart0*)0xE2900000)

typedef struct{
    unsigned int ULCON2;
    unsigned int UCON2;
    unsigned int UFCON2;
    unsigned int UMCON2;
    unsigned int UTRSTAT2;
    unsigned int UERSTAT2;
    unsigned int UFSTAT2;
    unsigned int UMSTAT2;
    unsigned int UTXH2;
    unsigned int URXH2;
    unsigned int UBRDIV2;
    unsigned int UDIVSLOT2;
    unsigned int INTP2;
    unsigned int UINTSP2;
    unsigned int UINTM2;
}uart2;
#define UART2   (*(volatile uart2*)0xE2900800)

void uart0_init(void)
{
    GPA0.GPA0CON &= ~(0xFF<<0); /* clear bit[7:0]  */
    GPA0.GPA0CON |= (0x22<<0);  /* enable GPA0_0/1 pin Uart Mode */
    UART0.ULCON0 = 0x3;         /*8 bit 1 stop No parity */
    UART0.UCON0 = 0x5;
    UART0.UMCON0 = 0;           /* Disable AFC */
    UART0.UFCON0 = 0;           /* Disable FIFO */
    UART0.UBRDIV0 = 35;         /* UBRDIV = (PCLK/(bpsx16)) - 1 */
    UART0.UDIVSLOT0 = 0x0888;   /**/
    printf("%s ok\n", __func__);
}

void uart0_putc(char c)
{
    while(!(UART0.UTRSTAT0 & (0x1<<1)));
    UART0.UTXH0 = c;
    if (c == '\n'){
        uart0_putc('\r');
    }
}

char uart0_getc(void)
{
    char data;
    while(!(UART0.UTRSTAT0 & (0x1<<0)));
    data = (UART0.URXH0 & 0x0f);

    if((data == '\n') || (data == '\r')){
        uart0_putc('\n');uart0_putc('\r');
    }else{
        uart0_putc(data);
    }

    return data;
}

void uart2_init(void)
{
    GPA1.GPA1CON = (GPA1.GPA1CON & ~(0xFF<<0)) | (0x22<<0);
    UART2.ULCON2 = 0x3;
    UART2.UCON2 = 0x5;
    UART2.UMCON2 = 0;
    UART2.UFCON2 = 0;
    UART2.UBRDIV2 = 35;
    UART2.UDIVSLOT2 = 0x0888;
    printf("%s ok\n", __func__);
}

void uart2_putc(char c)
{
    while(!(UART2.UTRSTAT2 & (0x1<<1)));
    UART2.UTXH2 = c;
    if (c == '\n'){
        uart2_putc('\r');
    }
}

char uart2_getc(void)
{
    char data;
    while(!(UART2.UTRSTAT2 & (0x1<<0)));
    data = (UART2.URXH2 & 0x0f);

    if((data == '\n') || (data == '\r')){
        uart2_putc('\n');uart2_putc('\r');
    }else{
        uart2_putc(data);
    }
    return data;
}

void putc(unsigned char c)
{
    uart0_putc(c);
}

unsigned char getc(void)
{
    return uart0_getc();	
}

void uart0_puts(const char *pstr)
{
    while(*pstr != '\0'){
        uart0_putc(*pstr++);
    }
}

void uart0_gets(char *p)
{
    char data;

    while((data = uart0_getc()) != '\r'){
        if(data == '\b'){
            p--;
        }
        *p++ = data;
    }

    if(data == '\r')
        *p++ = '\n';

    *p = '\0';
}

static void delay(volatile unsigned int i)
{
    while(i--);
}

#define DELAY_COUNT     (90000000)
void tester_uart(void)
{
    uart0_init();
    uart2_init();

    static unsigned int a = 0;
    for(;;){
        printf("uart test , a = %d.\n", a);
        delay(DELAY_COUNT);
        a ++;
    }
}
